﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Httlgd.DataCenter.Services.Common;
using Httlgd.DataCenter.Services.Core;
using Httlgd.DataCenter.Services.Core.Common;

using Httlgd.DataCenter.Services.Sms.DataTransferObject;
using Httlgd.DataCenter.Services.Sms.DataAccess.EntityFramework;

namespace Httlgd.DataCenter.Services.Sms.DataAccess
{
    public class SermonDAL : DataAccessorBase<SermonDTO, Sermon, SermonManagementEntities>
    {
        #region Contructors
        public SermonDAL()
            : base()
        {

        }

        public SermonDAL(SermonManagementEntities EFContext)
            : base(EFContext)
        {

        }
        #endregion

        #region Public Methods
        public void DeleteEntity(Object key)
        {
            //Delete Associated attachment
            //Delete Associated Bible scriptures
            //Delete associated SermonTagging
        }

        public DataTransferObjectCollectionBase<SermonDTO> Search(SermonSearchParameterDTO param)
        {
            DataTransferObjectCollectionBase<SermonDTO> result = new DataTransferObjectCollectionBase<SermonDTO>();
            result.Items = new List<SermonDTO>();


            return result;
        }

        public void UpdateSermonAudioFilePath(int sermonID, string audioFileName, string audioFilePath)
        {
            Sermon sermon = this.objectContext.Sermon.Where<Sermon>(s => s.ID == sermonID).FirstOrDefault<Sermon>();

            if (sermon == null)
            {
                throw new Exception(String.Format("Sermon with ID {0} does not existed.", sermonID));
            }

            sermon.FilePath = audioFilePath;
            sermon.FileName = audioFileName;
            this.objectContext.SaveChanges();
        }

        public string GetSermonAudioFilePath(int sermonID, out string fileName)
        {
            fileName = "";

            Sermon sermon = this.RetrieveEntity(sermonID);
            if (sermon == null)
                return "";

            fileName = sermon.FileName;
            return sermon.FilePath;
        }

        #endregion

        #region Overrided Methods
        protected override SermonDTO MapEntityToBusinessEntity_ForChildren(Sermon entity, SermonDTO businessEntity)
        {
            businessEntity = base.MapEntityToBusinessEntity_ForChildren(entity, businessEntity);

            //Attachments collection
            AttachmentDAL attachmentDAL = new AttachmentDAL();

            if (businessEntity.Attachments == null)
                businessEntity.Attachments = new List<AttachmentDTO>();

            if (!entity.Attachment.IsLoaded)
            {
                entity.Attachment.Load();
            }

            foreach (Attachment attachment in entity.Attachment)
            {
                businessEntity.Attachments.Add(attachmentDAL.MapEntityToBusinessEntity(attachment, null));
            }

            //BibleScriptures collection
            BibleScriptureDAL bibleScriptureDAL = new BibleScriptureDAL();

            if (businessEntity.BibleScriptures == null)
                businessEntity.BibleScriptures = new List<BibleScriptureDTO>();

            if (!entity.BibleScripture.IsLoaded)
            {
                entity.BibleScripture.Load();
            }

            foreach (BibleScripture bibleScripture in entity.BibleScripture)
            {
                businessEntity.BibleScriptures.Add(bibleScriptureDAL.MapEntityToBusinessEntity(bibleScripture, null));
            }

            //Tags collection
            TagDAL tagDAL = new TagDAL();
            if (businessEntity.Tags == null)
                businessEntity.Tags = new List<TagDTO>();

            if (!entity.SermonTagging.IsLoaded)
            {
                entity.SermonTagging.Load();
            }

            foreach (SermonTagging sermonTagging in entity.SermonTagging)
            {
                sermonTagging.TagReference.EnsureLoad();
                businessEntity.Tags.Add(tagDAL.MapEntityToBusinessEntity(sermonTagging.Tag, null));
            }

            return businessEntity;
        }

        protected override Sermon MapBusinessEntityToEntity_ScalarInner(SermonDTO businessEntity, Sermon entity)
        {
            entity = base.MapBusinessEntityToEntity_ScalarInner(businessEntity, entity);

            //SermonCategory
            entity.SermonCategory = this.objectContext.SermonCategory.Where(r => r.ID == businessEntity.SermonCategoryID).FirstOrDefault();

            //ServiceType
            entity.ServiceType = this.objectContext.ServiceType.Where(r => r.ID == businessEntity.ServiceTypeID).FirstOrDefault();

            //Speaker
            entity.Speaker = this.objectContext.Speaker.Where(r => r.ID == businessEntity.SpeakerID).FirstOrDefault();

            return entity;
        }

        public override void UpdateAssociatedData(SermonDTO businessEntity, Sermon entity)
        {
            base.UpdateAssociatedData(businessEntity, entity);

            entity.Attachment.EnsureLoad<Attachment>();

            //Attacthments
            if (businessEntity.Attachments != null)
            {
                AttachmentDAL attDAL = new AttachmentDAL(this.objectContext);
                List<int> attIDs = new List<int>();
                foreach (AttachmentDTO att in businessEntity.Attachments)
                {
                    att.SermonID = entity.ID;

                    AttachmentDTO attDTO = null;

                    if (att.ID > 0)
                        attDTO = attDAL.Update(att);
                    else
                        attDTO = attDAL.Insert(att);

                    attIDs.Add(attDTO.ID);
                }

                List<Attachment> removedAttachment = entity.Attachment.Where(att => (!attIDs.Contains(att.ID))).ToList();
                foreach (Attachment att in removedAttachment)
                {
                    entity.Attachment.Remove(att);
                    this.objectContext.DeleteObject(att);
                }
            }

            //Bible scripture
            if (businessEntity.BibleScriptures != null)
            {
                BibleScriptureDAL bsDAL = new BibleScriptureDAL(this.objectContext);
                List<int> bsIDs = new List<int>();
                foreach (BibleScriptureDTO bs in businessEntity.BibleScriptures)
                {
                    bs.SermonID = entity.ID;

                    BibleScriptureDTO bsDTO = null;

                    if (bs.ID > 0)
                        bsDTO = bsDAL.Update(bs);
                    else
                        bsDTO = bsDAL.Insert(bs);

                    bsIDs.Add(bsDTO.ID);
                }

                List<BibleScripture> removedBibleScripture = entity.BibleScripture.Where(bs => (!bsIDs.Contains(bs.ID))).ToList();
                foreach (BibleScripture bs in removedBibleScripture)
                {
                    entity.BibleScripture.Remove(bs);
                    this.objectContext.DeleteObject(bs);
                }
            }

            //Tags
            if (businessEntity.Tags != null)
            {
                List<TagDTO> newTagRefList = businessEntity.Tags.Where<TagDTO>(tagdto => entity.SermonTagging.Count<SermonTagging>(st => st.TagID == tagdto.ID) == 0).ToList<TagDTO>();
                foreach (TagDTO tagdto in newTagRefList)
                {
                    SermonTagging sermonTagging = new SermonTagging();                    
                    sermonTagging.TagID = tagdto.ID;

                    entity.SermonTagging.Add(sermonTagging);
                    //this.objectContext.AddObject(this.EntitySetName, sermonTagging);
                }

                List<SermonTagging> removedTags = entity.SermonTagging.Where(st => businessEntity.Tags.Count<TagDTO>(tagdto => tagdto.ID == st.TagID) == 0).ToList<SermonTagging>();
                foreach (SermonTagging tag in removedTags)
                {
                    entity.SermonTagging.Remove(tag);
                    this.objectContext.DeleteObject(tag);
                }
            }

            this.objectContext.SaveChanges();
        }
        #endregion

        #region Private funtionalities methods
        private int InsertSermonTagging(int sermonID, int tagID)
        {
            SermonTagging sermonTagging = new SermonTagging();
            sermonTagging.SermonID = sermonID;
            sermonTagging.TagID = tagID;

            this.objectContext.AddObject(this.EntitySetName, sermonTagging);
            this.objectContext.SaveChanges();

            return sermonTagging.ID;
        }
        #endregion
    }
}
